﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Data;
using System.Collections;

namespace OT.Common
{
    public class BaseDictionary
    {
        #region GetKeyListDictionary

        static public Dictionary<string, List<T>> GetKeyListDictionary<T>(string fieldName, IList objs)
        {
            Dictionary<string, List<T>> dict = new Dictionary<string, List<T>>();

            PropertyInfo pInfo = GetPropertyInfo<T>(fieldName);

            if (pInfo == null || objs == null)
                return dict;

            // 是否多级关联属性（包含点号）
            string fieldLast = HasDot(fieldName) ? GetLastField(fieldName) : string.Empty;

            foreach (T obj in objs)
            {
                string key = GetDotKeyValue<T>(fieldName, pInfo, fieldLast, obj);

                if (dict.ContainsKey(key))
                    dict[key].Add(obj);
                else
                {
                    List<T> list = new List<T>();
                    list.Add(obj);
                    dict.Add(key, list);
                }
            }

            return dict;
        }

        #endregion

        #region GetKeyDictionary

        static public Dictionary<string, T> GetKeyDictionary<T>(string keyName, IList objs)
        {
            Dictionary<string, T> dict = new Dictionary<string, T>();

            PropertyInfo pInfo = GetPropertyInfo<T>(keyName);

            if (pInfo == null || objs == null)
                return dict;

            // 是否多级关联属性（包含点号）
            string fieldLast = HasDot(keyName) ? GetLastField(keyName) : string.Empty ;

            foreach (T obj in objs)
            {
                string key = GetDotKeyValue<T>(keyName, pInfo, fieldLast, obj);

                dict.Add(key, obj);
            }

            return dict;

        }

        #endregion

        #region GetDupKeyDictionary

        static public Dictionary<string, T> GetDupKeyDictionary<T>(string keyName1, string keyName2, List<T> objs)
        {
            Dictionary<string, T> dict = new Dictionary<string, T>();

            PropertyInfo pInfo1 = GetPropertyInfo<T>(keyName1);

            PropertyInfo pInfo2 = GetPropertyInfo<T>(keyName2);

            if (pInfo1 == null || pInfo2 == null || objs == null)
                return dict;

            // 是否多级关联属性（包含点号）
            string fieldLast1 = HasDot(keyName1) ? GetLastField(keyName1) : string.Empty;
            string fieldLast2 = HasDot(keyName2) ? GetLastField(keyName2) : string.Empty;

            foreach (T obj in objs)
            {
                string key1 = GetDotKeyValue<T>(keyName1, pInfo1, fieldLast1, obj);
                string key2 = GetDotKeyValue<T>(keyName2, pInfo2, fieldLast2, obj);

                dict.Add(string.Format("{0}-{1}", key1, key2), obj);
            }

            return dict;

        }

        #endregion

        #region GetStringDictionary

        static public Dictionary<string, string> GetStringDictionary<T>(string keyName, string valueName, List<T> objs)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            PropertyInfo keyInfo = GetPropertyInfo<T>(keyName);
            PropertyInfo valueInfo = GetPropertyInfo<T>(valueName);

            if (keyInfo == null || valueInfo == null || objs == null)
                return dict;

            // 是否多级关联属性（包含点号）
            string keyLast = HasDot(keyName) ? GetLastField(keyName) : string.Empty;
            string valueLast = HasDot(valueName) ? GetLastField(valueName) : string.Empty;

            foreach (T obj in objs)
            {
                string key = GetDotKeyValue<T>(keyName, keyInfo, keyLast, obj);
                string value = GetDotKeyValue<T>(valueName, valueInfo, valueLast, obj);

                dict.Add(key, value);
            }

            return dict;
        }

        #endregion

        #region GetStringDictionary DataTable

        static public Dictionary<string, string> GetStringDictionary(string keyName, string valueName, DataTable dt)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            if (dt.Columns[keyName] == null || dt.Columns[valueName] == null)
                return dict;

            foreach (DataRow row in dt.Rows)
            {
                dict.Add(row[keyName].ToString(), row[valueName].ToString());
            }

            return dict;
        }

        #endregion

        #region GetPropertyInfo

        private static PropertyInfo GetPropertyInfo<T>(string keyName)
        {
            PropertyInfo pInfo = null;

            string keyField = keyName;
            if (HasDot(keyName))
                keyField = GetFirstField(keyName);

            PropertyInfo[] pInfos = typeof(T).GetProperties();
            foreach (PropertyInfo info in pInfos)
            {
                if (info.Name.Equals(keyField))
                {
                    pInfo = info;
                    break;
                }
            }
            return pInfo;
        }

        #endregion

        #region HasDot

        private static bool HasDot(string fieldName)
        {
            return fieldName.Contains(".");
        }

        #endregion

        #region GetFirstField

        private static string GetFirstField(string field)
        {
            int index = field.IndexOf(".");

            string ret = field;
            if (index > 0)
                ret = field.Substring(0, index);

            return ret;
        }

        #endregion

        #region GetLastField

        private static string GetLastField(string field)
        {
            int index = field.IndexOf(".");

            string ret = "";
            if (index > 0)
                ret = field.Substring(index+1, field.Length - index - 1);

            return ret;
        }

        #endregion

        #region GetListValue

        static public List<T> GetListValue<T>(Dictionary<string, List<T>> dict, string key)
        {
            List<T> rets = new List<T>();
            if (dict.ContainsKey(key))
                rets = dict[key];

            return rets;
        }

        #endregion

        #region GetDotFieldValue

        private static object GetDotFieldValue(string fieldName, object vObj)
        {
            PropertyInfo[] pInfos = vObj.GetType().GetProperties();

            string keyField = fieldName;
            if (HasDot(fieldName))
                keyField = GetFirstField(fieldName);

            PropertyInfo pInfo = null;
            foreach (PropertyInfo info in pInfos)
            {
                if (info.Name.Equals(keyField))
                {
                    pInfo = info;
                    break;
                }
            }

            object retObj = null;
            if (pInfo != null)
            {
                if (HasDot(fieldName))
                {
                    object obj = pInfo.GetValue(vObj, null);
                    retObj = GetDotFieldValue(GetLastField(fieldName), obj);
                }
                else
                {
                    retObj = pInfo.GetValue(vObj, null);
                }
            }

            return retObj;
        }

        #endregion

        #region GetDotKeyValue

        private static string GetDotKeyValue<T>(string fieldName, PropertyInfo pInfo, string fieldLast, T obj)
        {
            object vObj = pInfo.GetValue(obj, null);
            // 对于多级关联属性，继续检索
            if (HasDot(fieldName) && vObj != null)
                vObj = GetDotFieldValue(fieldLast, vObj);

            string key = string.Empty;
            if (vObj != null)
                key = vObj.ToString();
            return key;
        }

        #endregion

    }
}
